"""
!/usr/bin/env python
-*- coding: utf-8 -*-
@Author  : MarkJia
@Site    : 
@File    : 10、函数.py
"""

"""
函数是组织好的，可重复使用的。用来实现单一或相关功能的代码段
函数能提高应用的模块性和代码的重复利用率
"""
# 可分 内置函数 和 自定义函数

"""
def 函数名（参数:形式参数。可多个或不写）：
    函数体
    返回值
"""


def func_demo():
    # 函数体
    print('这是一个函数')


def func_with_params(a, b, c):
    """
    这是一个携带参数和注释的函数
    :param a:
    :param b:
    :param c:
    :return:
    """
    print(f'传入的参数为a={a},b={b},c={c}')


# 打印函数名称及注释
print(func_with_params.__doc__)
help(func_with_params)

# 调用函数，直接调用即可，注意传入实际参数
func_demo()  # 这是一个函数


# 定义空函数 : 函数注释 或者 pass
# 过滤关键字函数，没想好函数实现具体什么内容
def filter_char(s):
    """功能 ： 过滤敏感词"""
    pass


# 位置参数
func_with_params(3, 7, 9)  # 传入的参数为a=3,b=7,c=9

"""
形式参数 ： 定义函数时，函数名称后面括号的参数
实际参数 ： 调用函数时，函数后面括号的参数
"""


# 形式参数
def demo_func(a, b, c):
    print(a, b, c)


# 实际参数
demo_func(1, 2, 3)


# 少传参数 ： TypeError: demo_func() missing 1 required positional argument: 'c'
# 多传参数 ： TypeError: demo_func() takes 3 positional arguments but 4 were given
# ==============================================

# 关键字参数  赋值参数
def person(name, age):
    print(f'姓名为{name}')
    if age >= 18:
        print(f'{name}已成年')
    else:
        print(f'{name}未成年')


# 调用函数   关键字传参
person(age=19, name='MackJia')  # MackJia已成年
# 错误传参 person(20,'lily')


# 为参数设置默认值   放在最后面
from selenium import webdriver


def WebdriverWait(driver, timeout, poll_frequency=0.5):
    pass


# 传参时默认 poll_frequency=0.5
driver = webdriver.edge()
WebdriverWait(driver, 10)


# 错误案列 指定默认值参数放在最后
# try:
#     def wrong_demo(a=2,b,c):
#         pass
# except Exception as e:
#     print(f'抛出错误:{e}')


# 指定默认值一定是不可变对象：数字，字符，bool值，元组，不能为可变的列表或者字典、集合
# 错误示范，默认值为列表
# def wrong_demo2(a,b,c=[]):
#     c.append(a)
#     c.append(b)
#     print(a,b,c)
# 结果为：1 2 [1, 2]
# wrong_demo2(1,2)
# # 一直在上次基础上累加    结果为：3 4 [1, 2, 3, 4]
# wrong_demo2(3,4)


# 函数返回值
def sum(a, b):
    result = a + b
    # 函数返回值  返回多个值时是一组元组
    return result, a, b


# 调用时用变量接受，只有函数在被调用时，才会触发返回值
r = sum(2, 3)
print(r)  # 打印5和返回  元组 ： (5, 2, 3)

# 可变参数，不定长参数
"""
    1、*args 接受任意多个实际参数，存放在元组中
    2、使用已经存在的列表或者元组作为函数的可变参数，可以在列表的名称前加*
"""


def print_language(*args):
    print(args)
    # for i in args:
    #     print(i)


# 调用两次
print_language('Python', 'Js')  # ('Python', 'Js')
print_language('Python', 'Java', 'php', 'Ruby', 'Go')  # ('Python', 'Java', 'php', 'Ruby', 'Go')

# 传入列表、元组时解包
lan = ['中文', '英语', '法语', '非洲语言', '陕西话']
# 结果把整个列表当作元组的一个元素：(['中文', '英语', '法语', '非洲语言', '陕西话'],)
print_language(lan)
# 在形参 *args 中：收集所有的位置参数，放在元组中    在实参传入时，通过 *lan 将列表的位置参数解包
# 解包 结果是：('中文', '英语', '法语', '非洲语言', '陕西话')
print_language(*lan)

# **kwargs
"""
    1、接受任意多个类似关键字参数一样显式赋值的实际参数，并将其放到一个字典当中
    2、使用已存在字典作为函数的可变参数，可以在字典前面加 **
"""


def print_info(**kwargs):
    print(kwargs)


# {'Tom': 18, 'Lily': 16}
print_info(Tom=18, Lily=16)
# 存放在字典中 {'Tom': 18, 'Lily': 16, 'Anna': 19}
print_info(Tom=18, Lily=16, Anna=19)

# 注意解包。结果为{'code': 200, 'message': 'success', 'id': 11212311234}
data = {
    'code': 200,
    'message': 'success',
    'id': 11212311234
}
print_info(**data)
